#pragma once

#include <memory>
#include "Util.hpp"
#include "data.hpp"
#include "httplib.h"
#include <Windows.h>//Windows.h头文件包含的某些头文件和httplib.h里面的winsock2.h头文件里面包含的某些头文件会冲突,
					//Windows.h会判断某个头文件是否存在,不在就包含,在就不会,winsock2.h没有,所有Windows.h放在httplib.h后面不会报错,前面的话会报错
/*
	在对应文件夹下的自动备份
*/

namespace cloud
{
#define _server_ip "47.115.227.93"
#define _server_port 8080
	class Backup
	{
	private:
		std::string _back_dirctory;
		std::shared_ptr<DataManager> _data;
	public:
		Backup(const std::string back_dirctory,const std::string backup_file)
			:_back_dirctory(back_dirctory)
		{
			_data = std::shared_ptr<DataManager>(new DataManager(backup_file));
		}
		bool Upload(const std::string filename)
		{
			FileUtil file(filename);
			std::string str;
			file.GetContent(&str);//获取文件内容
			httplib::Client client(_server_ip,_server_port);//客户端
			httplib::MultipartFormData item;//构建请求
			item.content = str;
			item.filename = file.FileName();
			item.name = "file";
			item.content_type = "application/octet-stream";
			httplib::MultipartFormDataItems items;
			items.push_back(item);

			auto res = client.Post("/upload", items);//发起请求
			if (!res || res->status != 200)//判断是否上交成功
			{
				return false;
			}
			return true;
		}
		std::string GenerateFileId(const std::string filename)//生成对文件的描述id  文件名-大小-最后一次修改时间
		{
			FileUtil file(filename);
			std::stringstream ss;
			ss << file.FileName() << "-" << file.FileSize() << "-" << file.FileLastMTime();
			return ss.str();
		}
		bool IsNeedUpload(const std::string filename)
		{
			FileUtil file(filename);
			std::string old_id;
			if (_data->GetOneByKey(filename, &old_id) == true)//获取成功,证明是旧文件,旧文件需不需要上传取决于该文件有没有被修改
			{
				std::string new_id = GenerateFileId(filename);
				if (old_id == new_id)//相同表示文件没有进行修改过
				{
					return false;
				}
			}
			//来到这里,表示文件被修改过或者是新文件,两者都要进行提交

			if (time(NULL) - file.FileLastMTime() <= 3)//3秒之内修改过,就认定还在进行修改,不着急提交    防止该文件一直在修改，这边一直提交，导致效率低下，
			{																						  //等修改完,提交一次
				return false;
			}

			std::cout << file.FileName() << "is need to upload" << std::endl;
			return true;
		}
		void RunModule()
		{
			while (1)
			{
				FileUtil file(_back_dirctory);
				std::vector<std::string> _array;
				file.ScanDictory(&_array);//获取该目录下的所有文件
				for (auto& str : _array)
				{
					if (IsNeedUpload(str))//需要提交
					{
						Upload(str);//提交
						_data->Insert(str,GenerateFileId(str));//更新备份信息
					}
					Sleep(1);//防止没有文件需要提交时,进行无效遍历
				}
			}
		}
	};
};

